package com.hyjy.music.fragment

import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import android.view.LayoutInflater
import android.view.View
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.widget.SeekBar
import android.widget.SeekBar.OnSeekBarChangeListener
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.hyjy.music.*
import com.hyjy.music.base.BaseFragment
import com.hyjy.music.bean.MusicBean
import com.hyjy.music.databinding.FragmentMainBinding
import com.hyjy.music.fragment.LrcSettingsFragment.OnLrcStatusChangedListener
import com.hyjy.music.service.IService
import com.hyjy.music.service.IService.MusicListener
import com.hyjy.music.service.MusicService
import com.hyjy.music.util.*
import com.hyjy.music.TableLrcHelper.OnTableLrcLayoutClickListener
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.*

/**
 * 音乐播放Fragment
 */
class MainFragment : BaseFragment<FragmentMainBinding>(), ServiceConnection, View.OnClickListener {
    companion object {
        // 查询间隔
        const val QUERY_INTERVAL = 1000L

        // 上次播放的歌曲
        const val LAST_PLAY = "last_play"
    }

    // 音乐服务相关
    var myBinder: IService? = null
    lateinit var musicViewModel: MusicViewModel

    // Fragment相关
    private var musicListFragment: MusicListFragment? = null
    private var photoFragment: PhotoFragment? = null
    private var lrcFragment: LrcFragment? = null
    private var lrcSettingsFragment: LrcSettingsFragment? = null

    private var handler = Handler(Looper.getMainLooper())

    private var isReady = false

    // 缩放动画
    private var scaleAnimation: Animation? = null

    private val observer by lazy {
        androidx.lifecycle.Observer<MusicBean?> {
            updateUI(it)
        }
    }

    override fun initViewBinding(inflater: LayoutInflater): FragmentMainBinding {
        return FragmentMainBinding.inflate(inflater)
    }

    override fun initData() {
        init()
        addFragmentToViewPager()
        bindMusicService()
        setListener()
        // 根据播放模式显示正确的图标
        getInt(KEY_PLAY_MODE, 0) showPlayMode binding?.ivMode
    }

    private fun init() {
        lrcSettingsFragment = LrcSettingsFragment()
        scaleAnimation = AnimationUtils.loadAnimation(context, R.anim.scale)
        musicViewModel = ViewModelProvider(this)[MusicViewModel::class.java]
        // 如果用observe，应用不在前台时桌面歌词更新有延迟
        musicViewModel.currentMusicBean.observeForever(observer)
        musicViewModel.musicBeanList.observe(this) {
            handleDataChange(it)
        }
    }

    private fun updateUI(musicBean: MusicBean?) {
        mainFragmentUpdateUI(musicBean)
        musicListFragment?.updateUI()
        photoFragment?.updateUI(musicBean)
        lrcFragment?.updateUI(musicBean)
    }

    private fun handleDataChange(it: MutableList<MusicBean>) {
        // 歌曲正在播放的时候,去到文件管理增删歌曲触发下面的逻辑
        if (it.isEmpty()) {
            println("刷新音乐列表,没有歌曲")
            if (myBinder?.isMusicPlaying() == true) {
                myBinder?.pauseMusic()
            }
            // 没有歌曲了,当前播放的音乐置为null
            musicViewModel.updateCurrentMusicBean(null)
            return
        }
        println("刷新音乐列表,歌曲列表有值")
        if (isReady) {
            // 不是首次进入
            if (it.contains(musicViewModel.currentMusicBean.value)) {
                println("刷新音乐列表,当前播放的音乐仍然在列表中,无需处理")
            } else {
                println("刷新音乐列表,当前播放的音乐不在列表中,先暂停播放当前音乐,再播放第一首")
                if (myBinder?.isMusicPlaying() == true) {
                    myBinder?.pauseMusic()
                }
                val musicBean = musicViewModel.getMusicList()[0]
                myBinder?.startMusic(musicBean.url) // 先播放
                musicViewModel.updateCurrentMusicBean(musicBean)
            }
            return
        }
        // 首次进入,根据保存的播放进度继续播放
        val musicBean = getSerializableByName<MusicBean>(LAST_PLAY) ?: it[0]
        myBinder?.startMusic(musicBean.url) // 先播放
        myBinder?.seekMusicTo(musicBean.lastPlayProgress)
        musicViewModel.updateCurrentMusicBean(musicBean)
        isReady = true
    }

    private fun mainFragmentUpdateUI(musicBean: MusicBean?) {
        binding?.tvTitle?.text = musicBean?.title ?: ""
        binding?.tvSinger?.text = musicBean?.singer ?: ""
        binding?.seekBar?.max = musicBean?.duration?.toInt() ?: 0
        val playing = myBinder?.isMusicPlaying()
        binding?.musicControl?.ivPlay?.setImageResource(if (playing == true) R.drawable.ic_baseline_pause_circle else R.drawable.ic_baseline_play_circle)
    }

    private fun addFragmentToViewPager() {
        val fragmentList = mutableListOf<Fragment>()
        musicListFragment = MusicListFragment.newInstance().also {
            fragmentList.add(it)
        }
        photoFragment = PhotoFragment.newInstance().also {
            fragmentList.add(it)
        }
        lrcFragment = LrcFragment.newInstance().also {
            fragmentList.add(it)
        }
        binding?.vp?.adapter = object : FragmentStateAdapter(childFragmentManager, lifecycle) {
            override fun getItemCount(): Int {
                return fragmentList.size
            }

            override fun createFragment(position: Int): Fragment {
                return fragmentList[position]
            }
        }
        binding?.vpIndicator?.setViewPager(binding?.vp)
        binding?.vp?.offscreenPageLimit = fragmentList.size - 1
    }

    private fun bindMusicService() {
        val intent = Intent(context, MusicService::class.java)
        context?.bindService(intent, this, Context.BIND_AUTO_CREATE)
    }

    override fun onServiceConnected(name: ComponentName, service: IBinder) {
        myBinder = (service as? IService)?.apply {
            setMusicListener(object : MusicListener {
                // 音乐保存间隔
                val SAVE_GAP = 3000L

                // 上次保存的时间点
                var lastSaveTime = 0L

                override fun onMusicProgressChange(url: String, progress: Int, duration: Int) {
                    if (progress in 1..duration) {
                        lrcFragment?.rollLrc(url, progress.toLong(), duration.toLong())
                        binding?.tvCurrent?.text = progress.format()
                        binding?.tvDuration?.text = duration.format()
                        binding?.seekBar?.progress = progress
                    }
                    val currentTimeMillis = System.currentTimeMillis()
                    if (currentTimeMillis - lastSaveTime > SAVE_GAP) {
                        lastSaveTime = currentTimeMillis
                        saveMusic(progress)
                    }
                }

                override fun onMusicCompletion() {
                    when (getInt(KEY_PLAY_MODE, 0).toPlayMode()) {
                        PlayMode.ListLoop -> {
                            nextMusic() // 列表循环,逻辑等同于下一曲
                        }
                        PlayMode.RandomPlay -> {
                            randomPlay()
                        }
                        PlayMode.SingleLoop -> {
                            seekMusicTo(0)
                            musicViewModel.currentMusicBean.value?.let {
                                // 这里必须调用start方法
                                startMusic(it.url, false)
                            }
                            // 单曲循环不用更新UI
                        }
                    }
                }
            })
        }
        // 查询音乐列表
        musicViewModel.queryMusicList()
    }

    override fun onServiceDisconnected(name: ComponentName) {
        myBinder = null
    }

    // 实时保存播放进度,这样进程被杀下次也能恢复播放
    private fun saveMusic(progress: Int) {
        musicViewModel.currentMusicBean.value?.let {
            it.lastPlayProgress = progress
            lifecycleScope.launch(Dispatchers.IO) {
                val success = it saveSerializableByName LAST_PLAY
                println(if (success) "保存播放记录成功" else "保存播放记录失败")
            }
        }
    }

    private fun setListener() {
        binding?.musicControl?.ivPlay?.setOnClickListener(this)
        binding?.musicControl?.ivNext?.setOnClickListener(this)
        binding?.musicControl?.ivPrevious?.setOnClickListener(this)
        binding?.seekBar?.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
                if (fromUser) {
                    myBinder?.seekMusicTo(seekBar.progress)
                }
            }

            override fun onStartTrackingTouch(seekBar: SeekBar) {}
            override fun onStopTrackingTouch(seekBar: SeekBar) {}
        })
        // 播放模式
        binding?.ivMode?.setOnClickListener {
            var mode = getInt(KEY_PLAY_MODE, 0)
            ++mode showPlayMode binding?.ivMode
            putInt(KEY_PLAY_MODE, mode)
        }
        binding?.ivSettings?.setOnClickListener {
            lrcSettingsFragment?.show(childFragmentManager, "tag")
        }

        // 桌面歌词布局点击事件
        TableLrcHelper.setOnTableLrcLayoutClickListener(object : OnTableLrcLayoutClickListener {
            override fun onPlayButtonClick() {
                myBinder?.run {
                    handlePlayOrPause(this)
                }
            }

            override fun onPreButtonClick() {
                myBinder?.run {
                    previousMusic()
                }
            }

            override fun onNextButtonClick() {
                myBinder?.run {
                    nextMusic()
                }
            }
        })

        // 歌词设置对话框
        lrcSettingsFragment?.setOnLrcStatusChangedListener(object : OnLrcStatusChangedListener {
            override fun onLrcColorStatusChange(color: Int) {
                lrcFragment?.changeLrcColor(color)
                TableLrcHelper.setColor(color).refreshLrc()
            }

            override fun onLrcSizeStatusChange(size: Int) {
                lrcFragment?.changeLrcSize(size)
            }
        })

        // 监听音乐数据库的变化，有变化时刷新音乐列表
        musicViewModel.registerMusicChangeCallback {
            queryOnlyOnce()
        }
    }

    private fun queryOnlyOnce() {
        // 防抖,避免多次查询
        handler.removeCallbacksAndMessages(null)
        handler.postDelayed({ onMusicChange() }, QUERY_INTERVAL)
    }

    private fun onMusicChange() {
        // 再重新获取音乐列表
        musicViewModel.queryMusicList {
            // 这一行好像不能省略
            musicListFragment?.updateUI()
            showToast("刷新成功")
        }
    }

    override fun onClick(view: View?) {
        view?.startAnimation(scaleAnimation)
        myBinder?.run {
            when (view?.id) {
                R.id.iv_play -> handlePlayOrPause(this)
                R.id.iv_previous -> previousMusic()
                R.id.iv_next -> nextMusic()
            }
        }
    }

    /**
     * 播放或暂停
     */
    fun handlePlayOrPause(service: IService) {
        if (service.isMusicPlaying()) {
            service.pauseMusic()
        } else {
            musicViewModel.currentMusicBean.value?.let {
                service.startMusic(it.url, false)
            }
        }
        TableLrcHelper.setImageResource(if (service.isMusicPlaying()) R.drawable.ic_baseline_pause_circle else R.drawable.ic_baseline_play_circle)
        musicViewModel.currentMusicBean.value?.let {
            updateUI(it)
        }
    }

    /**
     * 上一曲
     */
    private fun IService.previousMusic() {
        var position = musicViewModel.getMusicPlayingPosition()
        if (position == -1) {
            return
        }
        position--
        if (position < 0) {
            position = musicViewModel.getMusicList().size - 1
        }
        switchMusic(this, musicViewModel.getMusicList()[position])
    }

    /**
     * 下一曲
     */
    private fun IService.nextMusic() {
        var position = musicViewModel.getMusicPlayingPosition()
        if (position == -1) {
            return
        }
        position++
        if (position > musicViewModel.getMusicList().size - 1) {
            position = 0
        }
        switchMusic(this, musicViewModel.getMusicList()[position])
    }

    /**
     * 随机播放
     */
    private fun IService.randomPlay() {
        val size = musicViewModel.getMusicList().size
        if (size == 0) {
            return
        }
        val position = Random().nextInt(Int.MAX_VALUE) % size
        switchMusic(this, musicViewModel.getMusicList()[position])
    }

    /**
     * 切换歌曲
     *
     * @param service 音乐播放接口
     * @param musicBean 音乐实体
     */
    fun switchMusic(service: IService, musicBean: MusicBean) {
        service.startMusic(musicBean.url)
        musicViewModel.updateCurrentMusicBean(musicBean)
    }

    fun setUniform(uniform: Boolean) {
        lrcFragment?.setUniform(uniform)
    }

    fun showTableLrc() {
        lrcFragment?.showTableLrc()
    }

    override fun onDestroy() {
        super.onDestroy()
        context?.unbindService(this)
        musicViewModel.currentMusicBean.removeObserver(observer)
        musicViewModel.unregisterMusicChangeCallback()
    }
}